/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package fr.univnantes.lina.uima.connectors.xml;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Pattern;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;

import org.apache.uima.UimaContext;
import org.apache.uima.analysis_component.CasAnnotator_ImplBase;
import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.CASRuntimeException;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.examples.SourceDocumentInformation;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.cas.StringArray;
import org.apache.uima.resource.ResourceInitializationException;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


/**
 * A multi-sofa annotator that does XML detagging. Reads XML data from the input Sofa (named
 * "xmlDocument"); this data can be stored in the CAS as a string or array, or it can be a URI to a
 * remote file. The XML is parsed using the JVM's default parser, and the plain-text content is
 * written to a new sofa called "plainTextDocument".
 */
public class XMLstax2CASAE extends JCasAnnotator_ImplBase  { //extends CasAnnotator_ImplBase {
	/**
	 * Name of optional configuration parameter that contains the name of an XML tag that appears in
	 * the input file. Only text that falls within this XML tag will be considered part of the
	 * "document" that it is added to the CAS by this CAS Initializer. If not specified, the entire
	 * file will be considered the document.
	 */
	public static final String PARAM_XMLTAG = "XmlTagContainingText";

	public static final String PARAM_XML_TAGS_TO_UNTAG = "XmlTagsToUntag";
	public static final String PARAM_XML_TAGS_TO_TURN_INTO_ANNOTATION = "XmlTagsToTurnIntoAnnotation";


	private SAXParserFactory parserFactory = SAXParserFactory.newInstance();

	private Type sourceDocInfoType;

	private String mXmlTagContainingText = null;
	private String[] XmlTagsToUntag = null;
	private HashMap<String, Integer> XmlTagsToTurnIntoAnnotationHashMap = null;

	/*
	 * LOCAL VARIABLES
	 */

	/*
	 *  Default view name if none are specified by the view parameter
	 */
	private static String DEFAULT_INPUT_VIEW = "_InitialView";

	/*
	 *  Default output view name 
	 */
	private static String DEFAULT_OUTPUT_VIEW = "plainTextDocument";


	public void initialize(UimaContext aContext) throws ResourceInitializationException {
		super.initialize(aContext);
		// Get config param setting
		mXmlTagContainingText  = (String) getContext().getConfigParameterValue(PARAM_XMLTAG);

		// Get config. parameter values
		XmlTagsToUntag = (String[]) aContext.getConfigParameterValue(PARAM_XML_TAGS_TO_UNTAG);

		// Get config. parameter values and initalize 
		String[]     XmlTagsToTurnIntoAnnotationStringArray = (String[]) aContext.getConfigParameterValue(PARAM_XML_TAGS_TO_TURN_INTO_ANNOTATION);
		XmlTagsToTurnIntoAnnotationHashMap = new HashMap<String, Integer>() ;
		if (XmlTagsToTurnIntoAnnotationStringArray != null)
			for (int i = 0; i < XmlTagsToTurnIntoAnnotationStringArray.length; i++) {
				XmlTagsToTurnIntoAnnotationHashMap.put(XmlTagsToTurnIntoAnnotationStringArray[i],1);
			}
	}

	public void typeSystemInit(TypeSystem aTypeSystem) throws AnalysisEngineProcessException {
		sourceDocInfoType = aTypeSystem.getType("org.apache.uima.examples.SourceDocumentInformation");
	}

	public void process(JCas aJCas) throws AnalysisEngineProcessException {
		// get handle to CAS view containing XML document
		// nh CAS xmlCas = aCAS.getView("xmlDocument");
		JCas xmlCas = null;
		try {
			xmlCas = aJCas.getView(DEFAULT_INPUT_VIEW);
		} catch (CASException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		InputStream xmlStream = xmlCas.getSofa().getSofaDataStream();

		XMLInputFactory f = XMLInputFactory.newInstance();
		XMLEventReader r = null;
		try {
			r = f.createXMLEventReader(xmlStream);

			while(r.hasNext()) {
				XMLEvent event = (XMLEvent) r.nextEvent();
				System.out.println("Debug: XMLEvent>"+event+"< " +
						"getCharacterOffset>"+event.getLocation().getCharacterOffset()+"< " +
								"getColumnNumber>"+event.getLocation().getColumnNumber()+"< "+
								"getLineNumber>"+event.getLocation().getLineNumber());
				// TODO event.getEventType()
			}	
		} catch (XMLStreamException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// create the plain text view and set its document text
		JCas plainTextView = null;
		try {
			plainTextView = aJCas.createView(DEFAULT_OUTPUT_VIEW);
		} catch (CASException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// parse with detag handler
		//		
		XMLSaxHandler handler = new XMLSaxHandler(plainTextView,mXmlTagContainingText, XmlTagsToTurnIntoAnnotationHashMap);
		//MUCSaxHandler handler = new MUCSaxHandler(plainTextView,mXmlTagContainingText, XmlTagsToTurnIntoAnnotationHashMap);
		//DetagHandler handler = new DetagHandler(xmlCas);

		try {
			SAXParser parser = parserFactory.newSAXParser();
			parser.parse(xmlStream, handler);
		} catch (Exception e) {
			throw new AnalysisEngineProcessException(e);
		}

		plainTextView.setDocumentText(handler.getDetaggedText());
		try {
			plainTextView.setDocumentLanguage(aJCas.getView(DEFAULT_INPUT_VIEW).getDocumentLanguage());
		} catch (CASRuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CASException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//SourceDocumentInformation sdi = new SourceDocumentInformation(plainTextView);
		//sdi.setBegin(0);
		//sdi.setEnd(handler.getDetaggedText().length());
		//	sdi.setDocumentSize((int) xmlfile.length());
		//sdi.setLastSegment(true);
		//sdi.setOffsetInSource(0);
		//sdi.setUri(xmlfile.toURI().toURL().toString()); // ugly but necessary : see XMIWriterCasConsumer implementation
		//sdi.addToIndexes();

		// suite au passage de CAS à JCas, le code suivant ne marche plus  
		// Index the SourceDocumentInformation object, if there is one, in the new sofa.
		// This is needed by the SemanticSearchCasIndexer
		//Iterator iter = xmlCas.getAnnotationIndex(sourceDocInfoType).iterator();
		//if (iter.hasNext()) {
		//	FeatureStructure sourceDocInfoFs = (FeatureStructure) iter.next();
		//	plainTextView.getIndexRepository().addFS(sourceDocInfoFs);
		//}

	}



}






